/*
 * @Author: Joel
 * @Date: 2025-04-12 09:01:59
 * @LastEditors: Joel
 * @LastEditTime: 2025-04-13 12:44:24
 * @FilePath: /smart-cupping2/usr/board_driver/ssd1315oled.c
 * @Description:
 * Copyright (C) 2025 YiJiaLink, All Rights Reserved.
 * 2025-04-12 09:01:59
 */
#include "ssd1315oled.h"

const unsigned char picture_tab[] = {
// 'battery-empty-solid', 64x56px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x80, 0xe0, 0xf0, 0xf0, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 
0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 
0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 
0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf0, 0xf0, 0xe0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
0x01, 0x01, 0x01, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xe0, 0xc0, 0x00, 0x00, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 
0x80, 0x80, 0x80, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x07, 0x03, 0x00, 0x00, 
0x00, 0x01, 0x07, 0x07, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x0f, 0x0f, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

volatile uint32_t g_ticks = 1000;

void delayMS(uint32_t n)
{
    g_ticks = n;
    while (g_ticks)
        ;
    return;
}
/**
 * @func:
 * @description: 发送命令
 * @param {unsigned char} command
 * @return {*}
 * @example:
 */
void Ins_trans(unsigned char command)
{
    unsigned char counter;
    PORT_ClrBit(OLED_CS_GPIO_PORT, OLED_CS_PIN);
    PORT_ClrBit(OLED_DC_GPIO_PORT, OLED_DC_PIN);
    for (counter = 0; counter < 8; counter++)
    {
        PORT_ClrBit(OLED_SCLK_GPIO_PORT, OLED_SCLK_PIN);
        if ((command & 0x80) >> 7)
            PORT_SetBit(OLED_SDIN_GPIO_PORT, OLED_SDIN_PIN);
        else
            PORT_ClrBit(OLED_SDIN_GPIO_PORT, OLED_SDIN_PIN);
        command = command << 1;
        __NOP();
        PORT_SetBit(OLED_SCLK_GPIO_PORT, OLED_SCLK_PIN);
        __NOP();
        PORT_ClrBit(OLED_SCLK_GPIO_PORT, OLED_SCLK_PIN);
    }
    PORT_SetBit(OLED_DC_GPIO_PORT, OLED_DC_PIN);
    PORT_SetBit(OLED_CS_GPIO_PORT, OLED_CS_PIN);
    return;
}
/**
 * @func:
 * @description: 发数据
 * @param {unsigned char} command
 * @return {*}
 * @example:
 */
void Data_trans(unsigned char command)
{
    unsigned char counter;
    PORT_ClrBit(OLED_CS_GPIO_PORT, OLED_CS_PIN);
    PORT_SetBit(OLED_DC_GPIO_PORT, OLED_DC_PIN);
    for (counter = 0; counter < 8; counter++)
    {
        PORT_ClrBit(OLED_SCLK_GPIO_PORT, OLED_SCLK_PIN);
        if ((command & 0x80) >> 7)
            PORT_SetBit(OLED_SDIN_GPIO_PORT, OLED_SDIN_PIN);
        else
            PORT_ClrBit(OLED_SDIN_GPIO_PORT, OLED_SDIN_PIN);
        command = command << 1;
        __NOP();
        PORT_SetBit(OLED_SCLK_GPIO_PORT, OLED_SCLK_PIN);
        __NOP();
        PORT_ClrBit(OLED_SCLK_GPIO_PORT, OLED_SCLK_PIN);
    }
    PORT_SetBit(OLED_DC_GPIO_PORT, OLED_DC_PIN);
    PORT_SetBit(OLED_CS_GPIO_PORT, OLED_CS_PIN);
    return;
}

void Column_set(unsigned char column)
{
    Ins_trans(0x10 | (column >> 4));
    Ins_trans(0x00 | (column & 0x0f));
    return;
}

void Page_set(unsigned char page)
{
    Ins_trans(0xb0 + page);
    return;
}

void Screen_clear()
{
    unsigned char page, column;
    for (page = 0; page < 7; page++) // page loop
    {
        Page_set(page);
        Column_set(32);
        for (column = 0; column < 64; column++) // column loop
        {
            Data_trans(0x00);
        }
    }
}

void Screen_fill(void)
{
    unsigned char page, column;
    for (page = 0; page < 7; page++) // page loop
    {
        Page_set(page);
        Column_set(32);
        for (column = 0; column < 64; column++) // column loop
        {
            Data_trans(0xff);
        }
    }
}

void Initial(void)
{

    Ins_trans(0xae); //--turn off oled panel

    Ins_trans(0x00); //--set low column address
    Ins_trans(0x10); //--set high column address

    Ins_trans(0x40); //--set start line address

    Ins_trans(0x20); //--Set Memory Addressing Mode
    Ins_trans(0x02);

    Ins_trans(0x81); //--set contrast control register
    Ins_trans(0xff);

    Ins_trans(0xa1); //--set segment re-map 127 to 0   a0:0 to seg127
    Ins_trans(0xc8); //--set com(N-1)to com0  c0:com0 to com(N-1)

    Ins_trans(0xa4); //--Resume to RAM content display

    Ins_trans(0xa6); //--set normal display

    Ins_trans(0xa8); //--set multiples ratio(1to64)
    Ins_trans(0x30); //--1/64 duty

    Ins_trans(0xd3); //--set display offset
    Ins_trans(0x00); //--not offset

    Ins_trans(0xd5); //--set display clock divide ratio/oscillator frequency
    Ins_trans(0x80); //--set divide ratio

    Ins_trans(0xd9); //--set pre-charge period
    Ins_trans(0xf1);

    Ins_trans(0xda); //--set com pins hardware configuration
    Ins_trans(0x12);

    Ins_trans(0xdb); //--set vcomh
    Ins_trans(0x40);

    Ins_trans(0x8d); //--set chare pump enable/disable
    Ins_trans(0x14); //--set(0x10) disable

    Screen_clear();
    delayMS(5);

    Ins_trans(0xAF);
    //--turn on oled panel
    return;
}
/**
 * @func:
 * @description: 图片显示
 * @param {unsigned char} *ptr_pic
 * @return {*}
 * @example:
 */
void Picture_display(const unsigned char *ptr_pic)
{
    unsigned char page, column;
    for (page = 0; page < 7; page++) // page loop
    {
        Page_set(page);
        Column_set(32);
        for (column = 0; column < 64; column++) // column loop
        {
            Data_trans(*ptr_pic++);
        }
    }
    delayMS(5);
    return;
}
/**
 * @func:
 * @description: 显示设置
 * @return {*}
 * @example:
 */
void disA5()
{
    unsigned char i, j;
    for (j = 0; j < 7; j++)
    {
        Page_set(j);
        Column_set(32);
        for (i = 0; i < 64; i++)
        {
            Data_trans(0xAA);
            Data_trans(0x55);
        }
    }
}

void oled_test(void)
{
    PORT_ClrBit(OLED_RES_GPIO_PORT, OLED_RES_PIN);
    delayMS(2);
    PORT_SetBit(OLED_RES_GPIO_PORT, OLED_RES_PIN);
    Initial();

    Screen_fill();
    delayMS(5);
    disA5();
    delayMS(5);
    Picture_display(picture_tab);
}
/***********************************************************************************************************************
 * Function Name: SysTick Handler
 * Description  : Decreament the g_ticks value
 * Arguments    : None
 * Return Value : None
 ***********************************************************************************************************************/
void SysTick_Handler(void)
{
    WDT->WDTE = 0xAC;
    g_ticks--;
}
